#! /usr/bin/env python

VERSION='0.1'
APPNAME='engine'

srcdir = '.'
blddir = 'build'

import os, sys, re, subprocess
import waf_ddf, waf_graphics, waf_dynamo, waf_gamesys, waf_physics, waf_render, waf_resource
from BuildUtility import BuildUtility, BuildUtilityException, create_build_utility
from waflib import Logs
import waflib.Options
import TestContext
from build_constants import TargetOS

test_context = None

def init(ctx):
    global test_context
    if 'build' in waflib.Options.commands:
        test_context = TestContext.create_test_context()

def options(opt):
    opt.recurse('src')
    opt.load('waf_dynamo')
    opt.load('waf_ddf')

def create_engine_version(self):
    engine_version = """
namespace dmEngineVersion
{
    static const char* PLATFORM = "%(platform)s";
    static const char* VERSION = "%(version)s";
    static const char* VERSION_SHA1 = "%(sha1)s";
}
"""
    full = self.outputs[0].abspath()

    try:
        os.mkdir(os.path.dirname(full))
    except:
        pass
    full = os.path.normpath(full)

    sha1 = self.env['ENGINE_SHA1']
    platform = self.env['ENGINE_PLATFORM']
    version = self.env['ENGINE_VERSION']
    with open(full, 'w') as f:
        f.write(engine_version % {"version": version, "sha1": sha1, "platform": platform})


def configure(conf):
    conf.load('waf_dynamo')
    conf.load('java')
    conf.load('waf_resource')
    target_os = conf.env['TARGET_OS']


    build_util = None
    try:
        build_util = create_build_utility(conf.env)
    except BuildUtilityException as ex:
        conf.fatal(ex.msg)

    waf_graphics.configure(conf)
    waf_ddf.configure(conf)
    waf_physics.configure(conf)
    waf_render.configure(conf)
    waf_gamesys.configure(conf)

    conf.recurse('src')

    architecture = build_util.get_target_architecture()

    simd_supported = True
    if target_os == TargetOS.WEB:
        simd_supported = False

    if not simd_supported and 'simd' in waflib.Options.options.enable_features:
        Logs.info("simd enabled")
        simd_supported = True

    sound_lib = []
    if waflib.Options.options.with_openal:
        sound_lib += ['sound_openal']
    elif simd_supported:
        sound_lib += ['sound']
    else:
        sound_lib += ['sound_nosimd']

    sound_lib += ['decoder_wav', 'decoder_ogg']
    glfw_lib = waf_dynamo.platform_get_glfw_lib(conf.env.PLATFORM)

    if target_os == TargetOS.MACOS:
        conf.env.append_value('LINKFLAGS', ['-framework', 'Cocoa', '-framework', 'OpenGL', '-framework', 'IOKit', '-framework', 'Carbon', '-framework', 'CoreVideo', '-framework', 'QuartzCore', '-framework', 'AVFoundation'])

        # For Vulkan/MoltenVK
        if waflib.Options.options.with_vulkan:
            # JG: for now, we only support validation layers on macos for x86_64 archs. I'll fix this later when/if needed.
            if architecture == 'x86_64':
                conf.env.append_value('LINKFLAGS', ['-framework', 'Metal', '-framework', 'Foundation', '-framework', 'IOSurface'])

                # Link with vulkan.dylib if the flag has been set (see graphics/vulkan/README.md) for more information
                conf.env.append_value('LINKFLAGS', ['-l', waflib.Options.options.with_vulkan_validation and 'vulkan' or 'MoltenVK'])

                # Metal deps requires libc++ stdlib. Remove once we've updated to use libc++ std
                conf.env.append_value('LINKFLAGS', ['-l', 'c++'])

    elif target_os == TargetOS.IOS:
        conf.env.append_value('LINKFLAGS', ['-framework', 'UIKit', '-framework', 'OpenGLES', '-framework', 'QuartzCore', '-framework', 'CoreGraphics', '-framework', 'AVFoundation'])

        # For Vulkan/MoltenVK
        if waflib.Options.options.with_vulkan and architecture == 'arm64':
            conf.env.append_value('LINKFLAGS', ['-l', 'MoltenVK', '-framework', 'Metal', '-framework', 'IOSurface'])
    elif target_os == TargetOS.ANDROID:
        conf.env.append_value('LINKFLAGS', ['-lEGL', '-lGLESv1_CM', '-lGLESv2', '-landroid', '-Wl,-soname=libdmengine.so'])
        conf.env['STLIB_CPP_RUNTIME'] = 'c++_static'

    elif target_os == TargetOS.WINDOWS:
        conf.env.append_value('LINKFLAGS', ['opengl32.lib', 'user32.lib', 'shell32.lib', 'xinput9_1_0.lib', 'dbghelp.lib', 'dinput8.lib', 'dxguid.lib'])

        if waflib.Options.options.with_vulkan:
            conf.env.append_value('LINKFLAGS', ['vulkan-1.lib'])

        if waflib.Options.options.with_dx12:
            conf.env.append_value('LINKFLAGS', ['D3D12.lib', 'DXGI.lib', 'D3DCompiler.lib'])

    elif target_os == TargetOS.WEB:
        pass

    conf.env['STLIB_EXTENSION'] = 'extension'
    conf.env['STLIB_RESOURCE'] = 'resource'
    conf.env['STLIB_RENDER'] = 'render render_font_default'.split()
    if 'box2dv3' in waflib.Options.options.enable_features:
        conf.env['STLIB_GAMESYS'] = 'gamesys gamesys_model gamesys_rig script_box2d'.split()
    else:
        conf.env['STLIB_GAMESYS'] = 'gamesys gamesys_model gamesys_rig script_box2d_defold'.split()
    conf.env['STLIB_GAMEOBJECT'] = 'gameobject'
    conf.env['STLIB_SCRIPT'] = 'script'
    conf.env['STLIB_DMGLFW'] = glfw_lib
    conf.env['STLIB_GUI'] = 'gui'
    conf.env['STLIB_PARTICLE'] = 'particle'
    conf.env['STLIB_RIG'] = 'rig'
    conf.env['STLIB_SOUND'] = sound_lib
    conf.env['STLIB_SOUND_NULL'] = 'sound_null'
    conf.env['LIB_OPENSLES'] = 'OpenSLES'
    conf.env['STLIB_LIVEUPDATE'] = 'liveupdate'

    if target_os != TargetOS.MACOS:
        conf.env['STLIB_UNWIND'] = 'unwind'

    conf.env['STLIB_PROFILEREXT'] = 'profilerext'
    conf.env['STLIB_PROFILEREXT_NULL'] = 'profilerext_null'
    conf.env['STLIB_PROFILER_REMOTERY'] = ['profiler_remotery']
    conf.env['STLIB_PROFILER_JS'] = ['profiler_js']

    conf.env['STLIB_TREMOLO'] = 'tremolo'

    conf.env['STLIB_OPUS'] = 'opus decoder_opus'.split()

    if target_os == TargetOS.LINUX:
        conf.env['LIB_OPENAL'] = 'openal'
    elif target_os == TargetOS.MACOS:
        pass
    elif target_os == TargetOS.WINDOWS and architecture == "x86":
        conf.env['LIB_OPENAL'] = 'OpenAL32'
        conf.env.append_value('INCLUDES', build_util.get_dynamo_ext("include", "AL"))

    conf.env.append_unique('DEFINES', 'DLIB_LOG_DOMAIN="ENGINE"')

def build(bld):
    global test_context

    # for the content build
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/gameobject'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/gamesys'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/graphics'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/input'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/particle'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/render'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/resource'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/rig'))
    sys.path.insert(0, os.path.join(bld.env.PREFIX, 'lib/python/script'))
    sys.path.insert(0, os.path.abspath('build/proto/engine'))
    sys.path.insert(0, os.path.abspath('proto/engine'))

    build_util = None
    try:
        build_util = create_build_utility(bld.env)
    except BuildUtilityException as ex:
        bld.fatal(ex.msg)

    bld.recurse('content')

    b = bld(rule = create_engine_version, target = 'engine_version.h', always = True)
    b.env['ENGINE_SHA1'] = build_util.git_sha1()
    b.env['ENGINE_PLATFORM'] = build_util.get_target_platform()
    b.env['ENGINE_VERSION'] = build_util.get_defold_version()

    bld.add_group()
    bld.recurse('src')

    bld.install_files('${PREFIX}/bin', 'scripts/dmengine_memprofile.sh', chmod=0O755)

    if build_util.get_target_os() in [TargetOS.WEB, TargetOS.MACOS, TargetOS.IOS]:
        srcPath = os.path.join('build', 'src')
        builds = ['','_release', '_headless']
        for build in builds:
            for suffix in ('.js.mem', '.js.symbols', '.js.map', '.wasm', '.wasm.map', '.wasm.debug.wasm', '.dSYM.zip'):
                filePath = os.path.join(srcPath, 'dmengine' + build + suffix)
                if (os.path.exists(filePath)):
                    bld.install_files('${PREFIX}/bin/%s' % bld.env.PLATFORM, filePath)
    TestContext.initialize_test_context(test_context, bld)

def shutdown(self):
    # unit tests disabled on win32 for now
    waf_dynamo.run_tests(test_context, valgrind = True)
